/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package baseObjects;

import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

/**
 *
 * @author yoav
 */
public class Language {

    private Vector<Symbol> symbolsVect = new Vector<Symbol>();
    private Symbol[] numeric = new Symbol[10];

    //TODO: yoav key restrictions:
    private Map<Character,Character> restrictions = null;

    public Language() {
    }

    public void setSymbolsVect(Vector<Symbol> symbolsVect) {
        this.symbolsVect = symbolsVect;
        for (Symbol symbol : symbolsVect) {
            assignNum(symbol);
        }
    }

    private void assignNum(Symbol symbol) {
        if (Character.isDigit(symbol.getRegular())) {
            numeric[Integer.parseInt(symbol.getRegular().toString())] = symbol;
            System.out.println("assigned " + symbol + " to number " + Integer.parseInt(symbol.getRegular().toString()));
        }
    }

    private void removeNum(Symbol symbol) {
        if (Character.isDigit(symbol.getRegular())) {
            numeric[Integer.parseInt(symbol.getRegular().toString())] = null;
            System.out.println("removed " + symbol + " from number " + Integer.parseInt(symbol.getRegular().toString()));
        }
    }

    public void add(Symbol sym) {
        symbolsVect.add(sym);
        assignNum(sym);

    }

    public Symbol remove(int pos) {
        removeNum(symbolsVect.get(pos));
        return symbolsVect.remove(pos);

    }

    public boolean contains(Object o){
        if (o==null) 
            return false;
        else{
            for (Symbol symbol : symbolsVect) {
                if (symbol.equals(o))
                    return true;
            }
        }
        return false;
    }

    public void clear() {
        symbolsVect.removeAllElements();
        if (numeric != null) {
            for (int i = 0; i < numeric.length; i++) {
                numeric[i] = null;

            }
        }
    }

    public void loadPropertiesFile(String filename) {
        try {
            Properties p = new Properties();
            p.load(new FileInputStream(new File(filename)));
            Map<String, Character> inv = new HashMap<String, Character>();
            for (Object key : p.keySet()) {
                String sKey = (String) key;
//                System.out.println("org val: "+p.getProperty(sKey));
//                System.out.println("inv key: "+ p.getProperty(sKey).split(",")[0]);
                inv.put(p.getProperty(sKey).split(",")[0], sKey.charAt(0));
            }
//            for (String key : inv.keySet()) {
//                System.out.println(key + " : "+inv.get(key));
//            }
            for (Object key : p.keySet()) {
                String s = (String) key;
                String[] keys = p.getProperty(s).split(",", 2);
                Symbol sym = new Symbol(s.charAt(0));
                if (keys.length > 1) {
                    //add the additional chars to the symbol
                    if (keys[1].contains("1")) {
                        sym.setShift(inv.get("1" + keys[0]));
                    }
                    if (keys[1].contains("2")) {
                        sym.setAlt(inv.get("2" + keys[0]));
                    }
                    if (keys[1].contains("3")) {
                        sym.setCtrl(inv.get("3" + keys[0]));
                    }
                } else if (keys[0].length() > 3) {
                    //check if the symbol exist as an additional char
                    for (Symbol sy : symbolsVect) {
                        Character c;
                        switch (keys[0].charAt(0)) {

                            case '1':
                                c = sy.getShift();
                                break;
                            case '2':
                                c = sy.getAlt();
                                break;
                            case '3':
                                c = sy.getCtrl();
                        }

                    }
                }
//                System.out.println("symbol: " + sym);
//                symbolsVect.add(sym);
                this.add(sym);
            }

        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }

    }

    public Character[] getArray() {
        Vector<Character> symbols = new Vector<Character>();
        symbolsVect.toArray();
        for (Symbol s : symbolsVect) {
            symbols.add(s.getRegular());
            Character shift = s.getShift();
            if (shift != null) {
                symbols.add(shift);
            }
            Character ctrl = s.getCtrl();
            if (ctrl != null) {
                symbols.add(ctrl);
            }
            Character alt = s.getAlt();
            if (alt != null) {
                symbols.add(alt);
            }
        }
        Character[] ans = new Character[symbols.size()];
        ans = symbols.toArray(ans);
        return ans;
    }

    public void updateProbability(Map<Character, Double> map) {
        for (Character c : map.keySet()) {
            for (Symbol symbol : symbolsVect) {
                if (symbol.equals(c)) {
                    symbol.updateProbability(map.get(c));
                    break;
                }
            }
        }
    }

    public void resetProbability() {
        for (Symbol symbol : symbolsVect) {
            symbol.setProbobility(0.0);
        }
    }

    public Vector<Symbol> getSymbolsSortet() {
        Vector<Symbol> ans = new Vector<Symbol>();
        ans.addAll(symbolsVect);
        for (int i = 0; i < ans.size(); i++) {
            for (int j = i + 1; j < ans.size(); j++) {
                if (ans.get(i).getProbobility() < ans.get(j).getProbobility()) {
                    Symbol tmp = ans.get(i);
                    Symbol tmp2 = ans.get(j);
                    ans.removeElement(tmp);
                    ans.removeElement(tmp2);
                    ans.insertElementAt(tmp2, i);
                    ans.insertElementAt(tmp, j);
                }
            }
        }
        return ans;
    }

    public Vector<Symbol> getSymbolsVect() {
        return symbolsVect;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Language) {
            return this.symbolsVect.equals(((Language) obj).symbolsVect);
        }
        return false;

    }

    public Symbol getNumber(int num) {
        return numeric[num];
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Symbol symbol : symbolsVect) {
            sb.append(symbol.toString());
            sb.append(System.getProperty("line.separator"));
        }
        sb.append("---------------------");
        sb.append("numeric\n");
        for (int i = 0; i < numeric.length; i++) {
            Symbol symbol = numeric[i];
            if (symbol == null) {
                sb.append(i + " = NULL");
            } else {
                sb.append(i + " = " + symbol);
            }
            sb.append(System.getProperty("line.separator"));
        }
        return sb.toString();
    }
}
